#include "timer.h"
#include "print.h"
#include "io.h"
#include "interrupt.h"
#include "print.h"
#include "thread.h"
#include "debug.h"

#define COUNTER0_OUTPUT_FREQ    100
#define COUNTER0_INPUT_FREQ     1193180
// #define COUNTER0_VALUE          (1193180 / 100)
#define COUNTER0_VALUE          11932
#define COUNTER0_VALUE_PORT     0x40
#define COUNTER0_NUM            0
#define COUNTER0_WORK_MODE      2
#define COUNTER0_IS_BCD         0
#define READ_WRITE_LATCH        3

#define PIC_CONTROL_PORT        0x43

#define MAKE_CONTROL_REG_VALUE(counter_num, rwl, mode, is_bcd) \
    ((counter_num << 6) | (rwl << 4) | (mode << 1) | (is_bcd))

/* 系统全局运行时间 */
uint32_t ticks = 0;

static void _timer_irq_handler(void){
    struct task_struct* _pcb = running_task();

    ASSERT(_pcb->magic_stack_limitation == 0x20030528);

    ticks ++;
    _pcb->ticks ++;

    if(_pcb->remainning_ticks == 0){
        schedule();
    }else{
        _pcb->remainning_ticks --;
    }
}

static void _frequency_set(uint8_t counter_port,
                           uint8_t control_reg_value,
                           uint16_t frequency_value){
    io_out_byte(PIC_CONTROL_PORT, control_reg_value);

    io_out_byte(counter_port, frequency_value & 0x00ff);
    io_out_byte(counter_port, (frequency_value & 0xff00) >> 8);
}

void timer_init(void){
    put_str("   timer_init start\n");
    /* modify by jianglin 2023-11-07 14:46
     * 由于interrupt中主pic的起始中断号修改为0x20
     * 8253的out0作为systick out0连接主pic的irq0
     * 所以此处修改为0x20
     */
    intr_register_callback(0x20, _timer_irq_handler);
    _frequency_set(COUNTER0_VALUE_PORT,
                   MAKE_CONTROL_REG_VALUE(COUNTER0_NUM, READ_WRITE_LATCH,
                                          COUNTER0_WORK_MODE, COUNTER0_IS_BCD),
                   COUNTER0_VALUE);
    
    put_str("   timer_init done\n\n");
}